﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Xml;
using System.Text.RegularExpressions;

namespace Magento.Generation
{
    class DI : Abstract
    {
        public bool readAndCreate(string dir)
        {
            if (!Directory.Exists(dir))
            {
                this.addMessage(dir + " Directory not exist.");
                return false;
            }
            
            string module_name = this.getModuleName(dir);
            if (module_name == null)
                return false;
            
            string[] files = Directory.GetFiles(dir, "di.xml", SearchOption.AllDirectories);

            if (files.Length == 0)
            {
                this.addMessage("di.xml file not exist.");
                return false;
            }

            foreach (string file in files) {
                if (!this.createFileForXml(dir, module_name, file)) {
                    return false;
                }
            }

            return true;
        }

        protected bool createFileForXml(string dir, string module_name, string path)
        {
            XmlDocument doc = new XmlDocument();
            XmlElement element;
            doc.Load(path);
            XmlNamespaceManager nsp = new XmlNamespaceManager(doc.NameTable);
            nsp.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");

            #region preference
            foreach (XmlNode _node in doc.SelectNodes(@"//config/preference"))
            {
                element = (XmlElement)_node;
                var parentClass = element.GetAttribute("for").ToString();
                var phpClass = element.GetAttribute("type").ToString();

                if (!phpClass.StartsWith(module_name.Replace("_", @"\")))
                {
                    this.addMessage($"{phpClass} 此类并不属于{module_name} 之下");
                    return false;
                }

                var _filePath = Regex.Replace(phpClass, "^"+module_name.Replace("_", @"\\"), dir) + ".php";
                var php = new PHP();
                if (php.setFullClassName(phpClass).setExtends(parentClass).toFile(_filePath)) {
                    this.addMessage($"{_filePath} created");
                }
            }
            #endregion

            #region type
            foreach (XmlNode _node in doc.SelectNodes(@"//config/type"))
            {
                element = (XmlElement)_node;
                var parentClass = element.GetAttribute("name").ToString();

                // plugin
                foreach (XmlNode _node2 in _node.SelectNodes("plugin"))
                {
                    element = (XmlElement)_node2;
                    var phpClass = element.GetAttribute("type").ToString();

                    if (!phpClass.StartsWith(module_name.Replace("_", @"\")))
                    {
                        this.addMessage($"{phpClass} 此类并不属于{dir} 之下");
                        return false;
                    }

                    var _filePath = Regex.Replace(phpClass, "^" + module_name.Replace("_", @"\\"), dir) + ".php";

                    var php = new PHP();
                    php.setFullClassName(phpClass);

                    var methods = new List<String>();
                    methods.Add($"public function beforeXxx(\\{parentClass} $subject, $param1) {{");
                    methods.Add("    return [$param1];");
                    methods.Add("}");
                    methods.Add("");
                    methods.Add($"public function afterXxx(\\{parentClass} $subject, $return) {{");
                    methods.Add("    return $return;");
                    methods.Add("}");
                    methods.Add("");
                    methods.Add($"public function aroundXxx(\\{parentClass} $subject, \\Closure $proceed) {{");
                    methods.Add("    return $proceed();");
                    methods.Add("}");
                    php.setMethod(methods);

                    if (php.toFile(_filePath))
                    {
                        this.addMessage($"{_filePath} created");
                    }
                }

                // argument
                foreach (XmlNode _node2 in _node.SelectNodes("arguments/argument[@xsi:type='object']", nsp))
                {
                    element = (XmlElement)_node2;
                    var phpClass = element.InnerText;

                    if (!phpClass.StartsWith(module_name.Replace("_", @"\")))
                    {
                        this.addMessage($"{phpClass} 此类并不属于{dir} 之下");
                        return false;
                    }

                    var _filePath = Regex.Replace(phpClass, "^" + module_name.Replace("_", @"\"), dir) + ".php";
                    var php = new PHP();
                    if (php.setFullClassName(phpClass).toFile(_filePath))
                    {
                        this.addMessage($"{_filePath} created");
                    }
                }
            }
            #endregion
            return true;
        }
    }
}
